package com.finance.console.service.budget;

import com.finance.console.common.Constant;
import com.finance.console.common.FinanceException;
import com.finance.console.dao.BudgetDAO;
import com.finance.console.entity.Budget;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class BudgetService {
    private final BudgetDAO budgetDAO = new BudgetDAO();
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    // 添加预算（完整对象，适配所有周期）
    public void addBudget(Budget budget) throws FinanceException {
        try {
            // 校验必要字段
            if (budget.getUserId() <= 0) {
                throw new FinanceException("用户ID不能为空");
            }
            if (budget.getCategory() == null || budget.getCategory().trim().isEmpty()) {
                throw new FinanceException("预算分类不能为空");
            }
            if (budget.getAmount() == null || budget.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                throw new FinanceException("预算金额必须大于0");
            }
            if (budget.getCycle() == null || !isValidCycle(budget.getCycle())) {
                throw new FinanceException("周期必须为：月/季度/年");
            }
            if (budget.getStartDate() == null || budget.getEndDate() == null) {
                throw new FinanceException("起止日期不能为空");
            }
            if (budget.getStartDate().after(budget.getEndDate())) {
                throw new FinanceException("开始日期不能晚于结束日期");
            }

            // 调用DAO插入数据
            int rows = budgetDAO.addBudget(budget);
            if (rows <= 0) {
                throw new FinanceException("添加预算失败");
            }
        } catch (SQLException e) {
            throw new FinanceException("数据库错误：添加预算失败", e);
        }
    }

    // 按用户ID和周期查询预算
    public List<Budget> getBudgetsByCycle(int userId, String cycle) {
        try {
            if (userId <= 0) {
                throw new FinanceException("用户ID无效");
            }
            if (!isValidCycle(cycle)) {
                throw new FinanceException("周期必须为：月/季度/年");
            }
            // 调用DAO查询（无日期限制，返回该用户该周期的所有预算）
            return budgetDAO.findByUserIdAndCycle(userId, cycle, null, null);
        } catch (SQLException e) {
            throw new FinanceException("查询预算失败", e);
        }
    }

    // 按budgetId更新金额
    public void updateBudgetById(int budgetId, BigDecimal newAmount) throws FinanceException {
        try {
            if (budgetId <= 0) {
                throw new FinanceException("预算ID无效");
            }
            if (newAmount == null || newAmount.compareTo(BigDecimal.ZERO) <= 0) {
                throw new FinanceException("新金额必须大于0");
            }

            int rows = budgetDAO.updateBudgetAmount(budgetId, newAmount);
            if (rows <= 0) {
                throw new FinanceException("更新失败：预算ID不存在");
            }
        } catch (SQLException e) {
            throw new FinanceException("数据库错误：更新预算失败", e);
        }
    }

    // 按budgetId删除
    public void deleteBudgetById(int budgetId) throws FinanceException {
        try {
            if (budgetId <= 0) {
                throw new FinanceException("预算ID无效");
            }

            int rows = budgetDAO.deleteBudget(budgetId);
            if (rows <= 0) {
                throw new FinanceException("删除失败：预算ID不存在");
            }
        } catch (SQLException e) {
            throw new FinanceException("数据库错误：删除预算失败", e);
        }
    }

    // 添加月度预算（快捷方法，自动计算起止日期）
    public void addMonthlyBudget(int userId, String category, double amount, String yearMonth) {
        try {
            // 校验年月格式
            if (!yearMonth.matches("\\d{4}-\\d{2}")) {
                throw new FinanceException("年月格式错误（正确：yyyy-MM）");
            }

            // 计算月度起止日期（如2024-11 -> 2024-11-01至2024-11-30）
            Date startDate = sdf.parse(yearMonth + "-01");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            calendar.add(Calendar.MONTH, 1);
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            Date endDate = calendar.getTime();

            // 构建Budget对象
            Budget budget = new Budget();
            budget.setUserId(userId);
            budget.setCategory(category);
            budget.setAmount(new BigDecimal(amount));
            budget.setCycle(Constant.CYCLE_MONTH); // 固定为月度周期
            budget.setStartDate(startDate);
            budget.setEndDate(endDate);

            // 调用通用添加方法
            addBudget(budget);
        } catch (ParseException e) {
            throw new FinanceException("日期解析错误：" + e.getMessage());
        } catch (FinanceException e) {
            // 捕获addBudget抛出的业务异常并复用信息
            throw new FinanceException("添加月度预算失败：" + e.getMessage());
        }
    }

    // 查询用户某月预算（基于月度预算的快捷查询）
    public List<Budget> getMonthlyBudgets(int userId, String yearMonth) {
        try {
            if (!yearMonth.matches("\\d{4}-\\d{2}")) {
                throw new FinanceException("年月格式错误（正确：yyyy-MM）");
            }

            // 解析当月第一天和最后一天（用于查询条件）
            Date startDate = sdf.parse(yearMonth + "-01");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            calendar.add(Calendar.MONTH, 1);
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            Date endDate = calendar.getTime();
            // 调用DAO查询当月预算（周期固定为"月"）
            return budgetDAO.findByUserIdAndCycle(userId, Constant.CYCLE_MONTH, startDate, endDate);
        } catch (ParseException e) {
            throw new FinanceException("日期解析错误：" + e.getMessage());
        } catch (SQLException e) {
            throw new FinanceException("查询月度预算失败", e);
        }
    }

    // 修改预算金额（兼容原逻辑的重载方法）
    public void updateBudget(int budgetId, double newAmount) {
        try {
            // 转换为BigDecimal调用通用更新方法
            updateBudgetById(budgetId, new BigDecimal(newAmount));
        } catch (FinanceException e) {
            throw new FinanceException("修改预算失败：" + e.getMessage());
        }
    }

    // 删除预算（兼容原逻辑的重载方法）
    public void deleteBudget(int budgetId) {
        try {
            deleteBudgetById(budgetId);
        } catch (FinanceException e) {
            throw new FinanceException("删除预算失败：" + e.getMessage());
        }
    }

    // 校验周期合法性
    private boolean isValidCycle(String cycle) {
        return Constant.CYCLE_MONTH.equals(cycle)
                || "季度".equals(cycle)
                || "年".equals(cycle);
    }
}